package com.springcloud.zuul.controller;

import com.springcloud.zuul.common.annotation.SysLog;
import com.springcloud.zuul.common.constant.Constant;
import com.springcloud.zuul.common.constant.ServiceCode;
import com.springcloud.zuul.common.utlis.ComUtils;
import com.springcloud.zuul.common.utlis.ConvertDateTime;
import com.springcloud.zuul.common.utlis.JsonResult;
import com.springcloud.zuul.common.validator.ValidatorUtils;
import com.springcloud.zuul.common.validator.group.AddGroup;
import com.springcloud.zuul.common.validator.group.UpdateGroup;
import com.springcloud.zuul.entity.SysMenuEntity;
import com.springcloud.zuul.entity.SysMenusEntity;
import com.springcloud.zuul.entity.SysProductEntity;
import com.springcloud.zuul.exception.ServiceException;
import com.springcloud.zuul.service.ShiroService;
import com.springcloud.zuul.service.SysMenuService;
import com.springcloud.zuul.service.SysProductService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 系统菜单
 */
@RestController
@RequestMapping("/sys/menu")
@Slf4j
@Api(tags = "权限功能")
public class SysMenuController extends AbstractController {
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private ShiroService shiroService;
    @Autowired
    private ComUtils comUtils;

    @Autowired
    SysProductService sysProductService;

    /**
     * Description:导航菜单
     * @author zhlu
     * @date 2020/1/8 1:39 下午
     * @param
     * @return com.springcloud.zuul.common.utlis.JsonResult
     */
    @GetMapping("/nav")
    @ApiOperation(notes = "导航菜单", value = "导航菜单")
    public JsonResult nav(String productId) {
        List<SysMenuEntity> menuList = sysMenuService.getUserMenuList(getUserId(),productId);
        Set<String> permissions = shiroService.getUserPermissions(getUserId(),productId);
        Map<String, Object> result = new HashMap<>();
        result.put("menuList", menuList);
        result.put("permissions", permissions);
        return JsonResult.success(result);
    }

    /**
     * 所有菜单列表
     */
    @GetMapping("/list")
    @RequiresPermissions("sys:menu:list")
    @ApiOperation(notes = "查看所有菜单列表", value = "查看所有菜单列表")
    public JsonResult list() {
        return sysMenuService.getMenuList();
    }

    /**
     * 选择菜单(添加、修改菜单)
     */
    @GetMapping("/select")
    @RequiresPermissions("sys:menu:select")
    @ApiOperation(notes = "查看选择菜单", value = "查看选择菜单")
    public JsonResult select() {
        //查询列表数据
        List<SysMenuEntity> menuList = sysMenuService.queryNotButtonList();

        //添加顶级菜单
        SysMenuEntity root = new SysMenuEntity();
        root.setMenuId("0");
        root.setMenuName("一级菜单");
        root.setOpen(true);
        root.setVerification(0);
        root.setFrequency(5);
        root.setOrderNum(0);
        root.setMarkId(0);
        menuList.add(root);

//        return JsonResult.success(listToTreeUtils.buidTree(JSON.parseArray(JSON.toJSONString(menuList)), "menuId", "parentId", "children"));
        return JsonResult.success(menuList);
    }

    /**
     * 菜单信息
     */
    @GetMapping("/info/{menuId}")
    @RequiresPermissions("sys:menu:info")
    @ApiOperation(notes = "查看菜单信息", value = "查看菜单信息")
    public JsonResult info(@PathVariable("menuId") String menuId) {
        SysMenuEntity menu = sysMenuService.queryByMenuId(menuId);
        //不存在当前菜单信息
        if (Objects.isNull(menu)) {
            return JsonResult.error(ServiceCode.MENU_NOT_EXISTED);
        }
        if (StringUtils.isNotEmpty(menu.getParentId()) &&
                !Constant.DEFAULT_PARENTID.equals(menu.getParentId())) {
            menu.setParentName(sysMenuService.queryByMenuId(menu.getMenuId()).getMenuName());
        }

        return JsonResult.success(menu);
    }

    /**
     * 保存
     */
    @SysLog("保存菜单")
    @PostMapping("/save")
    @RequiresPermissions("sys:menu:save")
    @ApiOperation(notes = "保存菜单", value = "保存菜单")
    public JsonResult save(@RequestBody SysMenuEntity menu) {
        //数据校验
        verifyForm(menu);

        //如果菜单编码不为空，获取是否重编码了
        if (StringUtils.isNotBlank(menu.getMenuId())) {
            if (sysMenuService.countByMenuId(menu.getMenuId()) > 0) {
                return JsonResult.error(ServiceCode.MENU_EXISTED);
            }
        } else {
            //系统自定义编码
            menu.setMenuId(comUtils.getLocalTrmSeqNumByLook("menu", "security", "sys_menu", "menu_id"));
        }

        menu.setInstm(ConvertDateTime.getCurrentTime());
        menu.setInsfnc(this.getClass().getSimpleName() + "." + Thread.currentThread().getStackTrace()[1].getMethodName());

        //保存于修改权限，处理
        handleMenu(menu);

        //数据验证
        ValidatorUtils.validateEntity(menu, AddGroup.class);

        sysMenuService.save(menu);

        return JsonResult.success();
    }

    /**
     * 修改
     */
    @SysLog("修改菜单")
    @PostMapping("/update")
    @RequiresPermissions("sys:menu:update")
    @ApiOperation(notes = "修改菜单", value = "修改菜单")
    public JsonResult update(@RequestBody SysMenuEntity menu) {
        //数据校验
        verifyForm(menu);

        SysMenuEntity countEenu = sysMenuService.queryByMenuId(menu.getMenuId());

        //存在当前菜单编码对象。并且guid是相等的，说明修改的是当前对象。
        if (Objects.nonNull(countEenu) && !countEenu.getGuId().equals(menu.getGuId())) {
            log.info("存在当前菜单编码的对象，但不是当前修改的对象");
            return JsonResult.error(ServiceCode.MENU_EXISTED);
        }

        //保存于修改权限，处理
        handleMenu(menu);

        //数据验证
        ValidatorUtils.validateEntity(menu, UpdateGroup.class);
        sysMenuService.updateById(menu);

        return JsonResult.success();
    }

    /**
     * Description:保存于修改权限，处理
     *
     * @param menu
     * @return com.springcloud.zuul.entity.SysMenuEntity
     * @author zhlu
     * @date 2020/1/8 11:12 上午
     */
    private SysMenuEntity handleMenu(SysMenuEntity menu) {
        //超级权限不能为空
        if (menu.getSuperAuthority() == null) {
            throw new ServiceException(ServiceCode.MENU_SUPER_AUTHORITY);
        }

        //是否超级权限。超级权限只用于权限管理平台   1.是   0否
        //产品权限需要关联对应的产品
        if (Constant.NOT_SUPER_AUTHORITY == menu.getSuperAuthority()) {
            //产品编码不能为空
            if (StringUtils.isEmpty(menu.getProductId())) {
                throw new ServiceException(ServiceCode.PRODUCT_ID_NULL);
            }
            //获取产品
            SysProductEntity productEntity = sysProductService.queryByProductId(menu.getProductId());
            //产品不存在
            if (Objects.isNull(productEntity)) {
                throw new ServiceException(ServiceCode.PRODUCT_NULL);
            }
            menu.setProductName(productEntity.getProductName());
        }
        //是否超级权限。超级权限只用于权限管理平台   1.是   0否
        //如果超级权限。不关联产品
        if (Constant.SUPER_AUTHORITY == menu.getSuperAuthority()) {
            menu.setProductId("");
            menu.setProductName("");
        }
        return menu;
    }

    /**
     * 删除
     */
    @SysLog("删除菜单")
    @PostMapping("/delete/{menuId}")
    @RequiresPermissions("sys:menu:delete")
    @ApiOperation(notes = "删除菜单", value = "删除菜单")
    public JsonResult delete(@PathVariable("menuId") String menuId) {

        //判断是否有子菜单或按钮
        List<SysMenuEntity> menuList = sysMenuService.queryListParentId(menuId,null);
        if (menuList.size() > 0) {
            return JsonResult.error(ServiceCode.THE_SUBMENU_FIRST);
        }
        sysMenuService.delete(menuId);

        return JsonResult.success();
    }

    /**
     * 验证参数是否正确
     */
    private void verifyForm(SysMenuEntity menu) {
        //权限功能名称不能为空
        if (StringUtils.isBlank(menu.getMenuName())) {
            throw new ServiceException(ServiceCode.MENU_NAME_NOT_NULL);
        }

        //上级权限功能不能为空
        if (menu.getParentId() == null) {
            throw new ServiceException(ServiceCode.MENU_PARENT_NULL);
        }

        //权限功能URL不能为空
        if (menu.getType() == Constant.MenuType.MENU.getValue()) {
            if (StringUtils.isBlank(menu.getUrl())) {
                throw new ServiceException(ServiceCode.MENU_URL_NOT_NULL);
            }
        }

        //上级菜单类型，如果父级菜单不为0时，去查询获取当前父级菜单资料
        int parentType = Constant.MenuType.CATALOG.getValue();
        if (!"0".equals(menu.getParentId())) {
            SysMenuEntity parentMenu = sysMenuService.queryByMenuId(menu.getParentId());
            parentType = parentMenu.getType();
        }

        //目录、菜单权限，上级权限功能只能为目录类型
        if (menu.getType() == Constant.MenuType.CATALOG.getValue() ||
                menu.getType() == Constant.MenuType.MENU.getValue()) {
            if (parentType != Constant.MenuType.CATALOG.getValue()) {
                throw new ServiceException(ServiceCode.MENU_PARENT_IS_CATALOG);
            }
            return;
        }

        //按钮权限，上级权限功能只能为菜单类型
        if (menu.getType() == Constant.MenuType.BUTTON.getValue()) {
            if (parentType != Constant.MenuType.MENU.getValue()) {
                throw new ServiceException(ServiceCode.MENU_PARENT_IS_CARTE);
            }
            return;
        }

        //效验权限、文档权限，上级权限功能只能为按钮类型
        if (menu.getType() == Constant.MenuType.EFFECT.getValue() ||
                menu.getType() == Constant.MenuType.DOCUMENTATION.getValue()) {
            if (parentType != Constant.MenuType.BUTTON.getValue()) {
                throw new ServiceException(ServiceCode.MENU_PARENT_IS_BUTTON);
            }
            return;
        }
    }

    /**
     * Description:获取相关产品、公司、角色菜单权限
     *
     * @param menusEntity
     * @return com.springcloud.zuul.common.utlis.JsonResult
     * @author zhlu
     * @date 2020/1/2 4:09 下午
     */
    @PostMapping("/related")
    @RequiresPermissions("sys:menu:list")
    @ApiOperation(notes = "查看相关菜单列表", value = "查看相关菜单列表")
    public JsonResult related(@RequestBody SysMenusEntity menusEntity) {
        return sysMenuService.queryMenusList(menusEntity);
    }
}
